package com.keta.foundation.controller;

import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.keta.foundation.dataFilter.DataFilter;
import com.keta.foundation.dataFilter.DataFilter.Operator;
import com.keta.foundation.dataFilter.DynamicSpecifications;
import com.keta.foundation.entity.Module;
import com.keta.foundation.entity.Organization;
import com.keta.foundation.entity.OrganizationRole;
import com.keta.foundation.entity.Role;
import com.keta.foundation.entity.User;
import com.keta.foundation.entity.UserRole;
import com.keta.foundation.log.Log;
import com.keta.foundation.log.LogUtil;
import com.keta.foundation.service.OrganizationRoleService;
import com.keta.foundation.service.OrganizationService;
import com.keta.foundation.service.RoleService;
import com.keta.foundation.service.UserRoleService;
import com.keta.foundation.service.UserService;
import com.keta.foundation.util.dwz.AjaxObject;
import com.keta.foundation.util.dwz.Page;

@Controller
@RequestMapping("/organization")
public class OrganizationController {

	private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

	private static final String ORGANIZATION_SHOW = "organization/tree_list";
	private static final String ORGANIZATION_TREE = "organization/tree";
	private static final String ORGANIZATION_LIST = "organization/list";
	private static final String ORGANIZATION_CREATE = "organization/create";
	private static final String ORGANIZATION_EDIT = "organization/edit";
	private static final String ORGANIZATION_VIEW = "organization/view";
	private static final String ORGANIZATION_LOOK_PARENT = "organization/lookup_parent";
	private static final String ORGANIZATION_ASSIGN_ROLE = "organization/assign_role";

	private static final Long ORGANIZATION_ROOT_ID = 1L;

	@Autowired
	private OrganizationService organizationService;

	@Autowired
	private OrganizationRoleService organizationRoleService;

	@Autowired
	private RoleService roleService;

	@RequiresPermissions("Organization:view")
	@RequestMapping("/tree_list")
	public String tree_list() {

		return ORGANIZATION_SHOW;
	}

	@RequiresPermissions("Organization:view")
	@RequestMapping("/tree")
	public String tree(HttpServletRequest request, Model model) {
		List<Organization> orgList = organizationService.getAll();
		model.addAttribute("orgList", orgList);

		return ORGANIZATION_TREE;
	}

	@RequiresPermissions("Organization:view")
	@RequestMapping("/list/{parentId}")
	public String list(@PathVariable Long parentId, ServletRequest request, Page page, Model model) {
		Specification<Organization> specification = DynamicSpecifications.byDataFilter(request, Organization.class,
				new DataFilter("parent.id", Operator.EQ, parentId));
		List<Organization> orgList = organizationService.getAll(specification, page);
		model.addAttribute("orgList", orgList);
		model.addAttribute("parentId", parentId);
		model.addAttribute("page", page);

		return ORGANIZATION_LIST;
	}

	@RequiresPermissions("Organization:view")
	@RequestMapping("/view/{orgId}")
	public String view(@PathVariable Long orgId, Model model) {
		Organization organization = organizationService.get(orgId);
		List<OrganizationRole> organizationRoles = organizationRoleService.getOrganizationRole(organization);
		model.addAttribute("organization", organization);
		model.addAttribute("organizationRoles", organizationRoles);
		return ORGANIZATION_VIEW;
	}

	@RequiresPermissions("Organization:create")
	@RequestMapping(value = "/create/{parentId}", method = { RequestMethod.GET })
	public String preCreate(@PathVariable Long parentId, Model model) {

		Organization organization = organizationService.get(parentId);

		model.addAttribute("organization", organization);

		return ORGANIZATION_CREATE;
	}

	@Log(message = "添加了部门:{0}")
	@RequiresPermissions("Organization:create")
	@RequestMapping(value = "/create", method = { RequestMethod.POST })
	public @ResponseBody String create(@Valid Organization organization) {

		organizationService.saveOrUpdate(organization);

		LogUtil.putArgs(new Object[] { organization.getName() });
		return AjaxObject.newOk("添加部门成功！").toString();
	}
	
	@RequiresPermissions("Organization:edit")
	@RequestMapping(value = "/edit/{orgId}", method = { RequestMethod.GET })
	public String preEdit(@PathVariable Long orgId, Model model) {

		Organization organization = organizationService.get(orgId);

		model.addAttribute("organization", organization);

		return ORGANIZATION_EDIT;
	}

	@Log(message = "修改了部门:{0}")
	@RequiresPermissions("Organization:edit")
	@RequestMapping(value = "/edit", method = { RequestMethod.POST })
	public @ResponseBody String edit(HttpServletRequest reuest, @Valid Organization organization) {

		organizationService.saveOrUpdate(organization);

		LogUtil.putArgs(new Object[] { organization.getName() });
		return AjaxObject.newOk("修改部门成功！").toString();
	}

	@Log(message = "删除了部门:{0}")
	@RequiresPermissions("Organization:delete")
	@RequestMapping("/delete/{orgId}")
	public @ResponseBody String delete(@PathVariable Long orgId) {

		organizationService.delete(orgId);

		LogUtil.putArgs(new Object[] { orgId });
		return AjaxObject.newOk("删除部门成功！").toString();
	}

	@RequiresPermissions("Organization:view")
	@RequestMapping("/lookupParent")
	public String lookupParent(Model model) {

		List<Organization> orgList = organizationService.getByParentId(ORGANIZATION_ROOT_ID);

		model.addAttribute("orgList", orgList);

		return ORGANIZATION_LOOK_PARENT;
	}

	@RequiresPermissions("Organization:assign")
	@RequestMapping(value = "/assign/{organizationId}")
	public String assign(@PathVariable Long organizationId, Model model) {

		Organization organization = organizationService.get(organizationId);

		List<Role> allRole = roleService.getAll();
		List<OrganizationRole> organizationRoles = organizationRoleService.getOrganizationRole(organization);
		List<Role> subRoles = new ArrayList<Role>();
		for (Role role : allRole) {
			boolean flag = false;
			for (OrganizationRole organizationRole : organizationRoles) {
				if (role.getId() == organizationRole.getRole().getId()) {
					flag = true;
				}
			}
			if (flag == false) {
				subRoles.add(role);
			}
		}

		model.addAttribute("organization", organization);
		model.addAttribute("organizationRoles", organizationRoles);
		model.addAttribute("subRoles", subRoles);
		return ORGANIZATION_ASSIGN_ROLE;
	}

	@Log(message = "向{0}用户分配了{1}角色")
	@RequiresPermissions("Organization:assign")
	@RequestMapping(value = "/assignRole", method = RequestMethod.POST)
	public @ResponseBody String assignRole(OrganizationRole organizationRole, Model model) {

		organizationRoleService.save(organizationRole);

		Organization organization = organizationService.get(organizationRole.getOrganization().getId());
		Role role = roleService.get(organizationRole.getRole().getId());
		LogUtil.putArgs(new Object[] { organization.getName(), role.getName() });
		return AjaxObject.newOk("").toString();
	}

	@Log(message = "撤销了{0}用户的{1}角色")
	@RequiresPermissions("Organization:assign")
	@RequestMapping(value = "/undoRole", method = RequestMethod.POST)
	public @ResponseBody String undoRole(OrganizationRole organizationRole, Model model) {
		organizationRole = organizationRoleService.get(organizationRole.getId());
		organizationRoleService.delete(organizationRole);

		LogUtil.putArgs(
				new Object[] { organizationRole.getOrganization().getName(), organizationRole.getRole().getName() });
		return AjaxObject.newOk("").toString();
	}

}
